package com.whmall.service.crm.module.companybusinesscertificate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.whmall.component.service.AbstractDbService;
import com.whmall.component.util.DateUtils;
import com.whmall.service.crm.entity.dto.companybusinesscertificate.*;
import com.whmall.service.crm.module.company.dao.CompanyMapper;
import com.whmall.service.crm.module.company.entity.CompanyDO;
import com.whmall.service.crm.module.companybusinesscertificate.dao.CompanyBusinessCertificateAttachmentMapper;
import com.whmall.service.crm.module.companybusinesscertificate.dao.CompanyBusinessCertificateMapper;
import com.whmall.service.crm.module.companybusinesscertificate.entity.CompanyBusinessCertificateAttachmentDO;
import com.whmall.service.crm.module.companybusinesscertificate.entity.CompanyBusinessCertificateDO;
import com.whmall.service.crm.module.companybusinesscertificate.entity.qo.CompanyBusinessCertificateQO;
import com.whmall.service.crm.module.companybusinesscertificate.service.CompanyBusinessCertificateService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Author：yangdong
 * Date：2020/8/3
 * Description：经营证件业务层实现
 */
@RequiredArgsConstructor
@Service
public class CompanyBusinessCertificateServiceImpl
        extends AbstractDbService<CompanyBusinessCertificateMapper, CompanyBusinessCertificateDO>
        implements CompanyBusinessCertificateService {

    private final CompanyBusinessCertificateMapper certificateMapper;
    private final CompanyBusinessCertificateAttachmentMapper certificateAttachmentMapper;
    private final CompanyMapper companyMapper;

    @Override
    public List<CompanyBusinessCertificateRspDTO> listBy(CompanyBusinessCertificateQueryReqDTO queryReqDTO) {
        CompanyBusinessCertificateQO qo = new CompanyBusinessCertificateQO();
        BeanUtils.copyProperties(queryReqDTO, qo);
        List<CompanyBusinessCertificateDO> certificateDOList = certificateMapper.listBy(qo);
        if (certificateDOList.isEmpty()) {
            return new ArrayList<>();
        }

        List<CompanyBusinessCertificateRspDTO> rspDTOList = certificateDOList.stream()
                .map(e -> {
                    CompanyBusinessCertificateRspDTO rspDTO = new CompanyBusinessCertificateRspDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    rspDTO.setEffectiveStartDate(DateUtils.filterDate(rspDTO.getEffectiveStartDate()));
                    rspDTO.setEffectiveEndDate(DateUtils.filterDate(rspDTO.getEffectiveEndDate()));
                    rspDTO.setIsEnabled(e.getEffective().equals(1));
                    return rspDTO;
                }).collect(Collectors.toList());
        if (queryReqDTO.isIncludeAttachmentUrl()) {
            Map<Long, List<String>> attachmentUrlMap = certificateAttachmentMapper.listByCertificateIds(certificateDOList
                            .stream().map(CompanyBusinessCertificateDO::getId)
                            .collect(Collectors.toList()))
                    .stream()
                    .collect(Collectors.groupingBy(CompanyBusinessCertificateAttachmentDO::getCertificateId,
                            Collectors.mapping(CompanyBusinessCertificateAttachmentDO::getAttachmentUrl,
                                    Collectors.toList())));
            rspDTOList.forEach(e -> e.setCertificateUrlList(attachmentUrlMap.get(e.getId())));
        }
        return rspDTOList;
    }

    @Override
    public List<CompanyBusinessCertificateDTO> listBy(CompanyBusinessCertificateListQO qo) {
        return this.list(new LambdaQueryWrapper<CompanyBusinessCertificateDO>()
                        .eq(qo.getCompanyId() != null, CompanyBusinessCertificateDO::getCompanyId, qo.getCompanyId())
                        .eq(qo.getEffective() != null, CompanyBusinessCertificateDO::getEffective, qo.getEffective())
                        .eq(qo.getDeleted() != null, CompanyBusinessCertificateDO::getDeleted, qo.getDeleted())
                        .in(CollUtil.isNotEmpty(qo.getCertificateTypes()), CompanyBusinessCertificateDO::getCertificateType, qo.getCertificateTypes())
                        .eq(qo.getEffectiveEndDate() != null, CompanyBusinessCertificateDO::getEffectiveEndDate, qo.getEffectiveEndDate()))
                .stream().map(cbc -> BeanUtil.copyProperties(cbc, CompanyBusinessCertificateDTO.class))
                .collect(Collectors.toList());
    }

    @Override
    public CompanyBusinessCertificateRspDTO getById(Long id) {
        CompanyBusinessCertificateDO certificateDO = certificateMapper.getById(id);
        CompanyBusinessCertificateRspDTO certificateRspDTO = new CompanyBusinessCertificateRspDTO();
        BeanUtils.copyProperties(certificateDO, certificateRspDTO);
        if (certificateDO.getEffective().equals(1)) {
            certificateRspDTO.setIsEnabled(true);
        } else {
            certificateRspDTO.setIsEnabled(false);
        }
        CompanyDO companyDO = companyMapper.selectById(certificateDO.getCompanyId());
        certificateRspDTO.setCompanyName(companyDO.getName());
        if (certificateRspDTO != null) {
            List<CompanyBusinessCertificateAttachmentDO> certificateAttachmentDOList = certificateAttachmentMapper.listByCertificateId(certificateDO.getId());
            certificateRspDTO.setCertificateUrlList(certificateAttachmentDOList
                    .stream()
                    .map(e -> e.getAttachmentUrl())
                    .collect(Collectors.toList()));
        }

        return certificateRspDTO;
    }

    @Override
    @Transactional
    public void insert(SaveCompanyBusinessCertificateReqDTO businessCertificateReqDTO) {
        CompanyBusinessCertificateDO certificateDO = new CompanyBusinessCertificateDO();
        BeanUtils.copyProperties(businessCertificateReqDTO, certificateDO);
        if (businessCertificateReqDTO.getIsEnabled()) {
            certificateDO.setEffective(1);
        } else {
            certificateDO.setEffective(Integer.parseInt(String.valueOf(System.currentTimeMillis() / 1000)));
        }
        certificateDO.setCreateType(businessCertificateReqDTO.getOperatorType());
        certificateDO.setCreateId(businessCertificateReqDTO.getOperatorId());
        certificateDO.setCreateTime(new Date());
        certificateDO.setUpdateType(businessCertificateReqDTO.getOperatorType());
        certificateDO.setUpdateId(businessCertificateReqDTO.getOperatorId());
        certificateDO.setUpdateTime(new Date());
        certificateMapper.insert(certificateDO);
        if (!CollectionUtils.isEmpty(businessCertificateReqDTO.getCertificateUrlList())) {
            certificateAttachmentMapper.batchInsert(businessCertificateReqDTO.getCertificateUrlList()
                    .stream()
                    .map(e -> CompanyBusinessCertificateAttachmentDO
                            .builder()
                            .attachmentUrl(e)
                            .certificateId(certificateDO.getId())
                            .build())
                    .collect(Collectors.toList()));

        }
    }


    @Override
    @Transactional
    public void update(SaveCompanyBusinessCertificateReqDTO businessCertificateReqDTO) {
        CompanyBusinessCertificateDO certificateDO = new CompanyBusinessCertificateDO();
        BeanUtils.copyProperties(businessCertificateReqDTO, certificateDO);
        if (businessCertificateReqDTO.getIsEnabled()) {
            certificateDO.setEffective(1);
        } else {
            certificateDO.setEffective(Integer.parseInt(String.valueOf(System.currentTimeMillis() / 1000)));
        }
        certificateDO.setUpdateType(businessCertificateReqDTO.getOperatorType());
        certificateDO.setUpdateId(businessCertificateReqDTO.getOperatorId());
        certificateDO.setUpdateTime(new Date());
        certificateMapper.update(certificateDO);
        // 旧附件列表
        List<CompanyBusinessCertificateAttachmentDO> certificateAttachmentList = certificateAttachmentMapper.listByCertificateId(certificateDO.getId());
        if (!CollectionUtils.isEmpty(businessCertificateReqDTO.getCertificateUrlList())) {
            // 新增的附件
            List<CompanyBusinessCertificateAttachmentDO> addCertificateAttachmentList = businessCertificateReqDTO.getCertificateUrlList()
                    .stream()
                    .filter(e -> certificateAttachmentList
                            .stream()
                            .noneMatch(ca -> ca.getAttachmentUrl().equals(e)))
                    .map(e -> CompanyBusinessCertificateAttachmentDO
                            .builder()
                            .attachmentUrl(e)
                            .certificateId(certificateDO.getId())
                            .build())
                    .collect(Collectors.toList());
            // 删除的附件
            List<Long> removeCertificateAttachmentIds = certificateAttachmentList
                    .stream()
                    .filter(e -> !businessCertificateReqDTO.getCertificateUrlList().contains(e.getAttachmentUrl()))
                    .map(CompanyBusinessCertificateAttachmentDO::getId)
                    .collect(Collectors.toList());
            if (addCertificateAttachmentList.size() > 0) {
                certificateAttachmentMapper.batchInsert(addCertificateAttachmentList);
            }
            if (removeCertificateAttachmentIds.size() > 0) {
                certificateAttachmentMapper.batchDelete(removeCertificateAttachmentIds, Integer.parseInt(String.valueOf(System.currentTimeMillis() / 1000)));
            }
        }
    }

    @Override
    public int delete(Long id, Integer operatorType, Long operatorId) {
        CompanyBusinessCertificateDO certificateDO = new CompanyBusinessCertificateDO();
        Integer deletedTimestamp = Integer.parseInt(String.valueOf(System.currentTimeMillis() / 1000));
        certificateDO.setId(id);
        certificateDO.setEffective(deletedTimestamp);
        certificateDO.setDeleted(deletedTimestamp);
        certificateDO.setUpdateType(operatorType);
        certificateDO.setUpdateId(operatorId);
        certificateDO.setUpdateTime(new Date());
        return certificateMapper.update(certificateDO);
    }


    @Override
    public int countEffective(Long id, Long companyId, String certificateNumber) {
        return certificateMapper.countEffective(id, companyId, certificateNumber);
    }

    @Override
    public void revalidateEffective() {
        certificateMapper.revalidateEffective();
    }

    @Override
    public Boolean isExistsValidProduct(Long id) {
        return certificateMapper.validProductCount(id) > 0;
    }

}
